<!doctype html>
<head>
	<meta charset="utf-8">
	<title>HTML5 Sortable library</title>
  <link rel="stylesheet" href="basscss.css">
  <script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
  <script src="html5sortable.js"></script>
</head>
<body>
	<div class="clearfix mb2 white bg-navy">
		<div class="left">
		  <a href="index.html" class="button py2 m0 button-transparent">HTML5 Sortable</a>
		</div>
		<div class="right">
			<a href="https://github.com/lukasoppermann/html5sortable/fork" class="button py2 m0 button-transparent">Fork on GitHub</a>
		</div>
	</div>
	<div class="px2 sm-px3 py2 mb3 col-8 mx-auto">
		<section class="mb3 mx-auto col col-12">
		  <div class="p3 navy bg-yellow">
		    <div class="flex flex-column">
		      <h1 class="h1 m0 flex-auto">
		        HTML5 Sortable
		      </h1>
			    <h2 class="h3 m0">
					Lightweight standalone library for creating sortable lists and grids using native HTML5 drag and drop API.
			    </h2>
		    </div>
		    <div class="sm-flex flex-center mxn2">
		      <div class="flex-auto px0 py2">
						<ul>
							<li>Only 2.54KB (minified and gzipped).</li>
							<li>Built using native HTML5 drag and drop API.</li>
							<li>Supports both list and grid style layouts.</li>
							<li><a href="https://github.com/lukasoppermann/html5sortable">Installation, support & more.</a></li>
						</ul>
		      </div>
		    </div>
		  </div>
		</section>
		<section class="mb3 mx-auto col col-12">
  		<div class="p3 clearfix bg-navy yellow">
				<div class="col col-6">
			    <h2 class="h3 m0">
						Sortable List
			    </h2>
					<div class="mt2 p2 bg-navy border yellow border-yellow">
				    <code class="mb0">
							<div>sortable('.o-sortable', {</div>
							<div class="px2 muted">
								forcePlaceholderSize: true,<br />
								placeholderClass: 'ph-class', <br />
								hoverClass: 'bg-maroon yellow', <br />
							</div>
							<div>});</div>
						</code>
  				</div>
		    </div>
				<div class="col col-6">
					<ul class="ml4 js-sortable sortable list flex flex-column list-reset">
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 1</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 2</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 3</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 4</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 5</li>
					</ul>
          <button class="ml4 js-serialize-button button navy bg-yellow">Serialize</button>
					<script type="text/javascript">
						sortable('.js-sortable', {
							forcePlaceholderSize: true,
							placeholderClass: 'mb1 bg-navy border border-yellow',
							hoverClass: 'bg-maroon yellow',
              itemSerializer: function (item, container) {
                item.parent = '[parentNode]'
                item.node = '[Node]'
                item.html = item.html.replace('<','&lt;')
                return item
              },
              containerSerializer: function (container) {
                container.node = '[Node]'
                return container
              }
						})
            document.querySelector('.js-serialize-button').addEventListener('click', function () {
              let serialized = sortable('.js-sortable', 'serialize')
              document.querySelector('.serialized-content').innerHTML = JSON.stringify(serialized, null, ' ')
            })
					</script>
		    </div>
			</div>
      <div class="p2 bg-navy border-top yellow border-yellow">
        <h5>Serialized:</h5>
        <code>
          <pre class="serialized-content">
          </pre>
        </code>
      </div>
		</section>
		<section class="mb3 mx-auto col col-12">
  		<div class="p3 clearfix bg-yellow maroon">
				<div class="col col-12 mb1">
			    <h2 class="h3 m0">
						Sortable Grid
			    </h2>
				</div>
				<div class="col col-6">
					<div class="p2 bg-yellow border maroon border-maroon mt1">
				    <code class="mb0">
							<div>sortable('.o-sortable', {</div>
							<div class="px2 muted">// options</div>
							<div>});</div>
						</code>
  				</div>
		    </div>
				<div class="col col-6">
					<div class="js-grid sortable grid clearfix ml4 myn1">
						<div class="col col-4 px2 py1">
							<div class="bg-maroon py3 yellow center">1</div>
						</div>
						<div class="col col-4 px2 py1">
							<div class="bg-maroon py3 yellow center">2</div>
						</div>
						<div class="col col-4 px2 py1">
							<div class="bg-maroon py3 yellow center">3</div>
						</div>
						<div class="col col-4 px2 py1">
							<div class="bg-maroon py3 yellow center">4</div>
						</div>
						<div class="col col-4 px2 py1">
							<div class="bg-maroon py3 yellow center">5</div>
						</div>
					</div>
		    </div>
			</div>
		</section>
		<section class="mb3 mx-auto col col-12">
  		<div class="p3 clearfix bg-maroon orange">
				<div class="col col-6">
			    <h2 class="h3 m0">
						Exclude items & nested list
			    </h2>
					<div class="mt2 p2 bg-maroon border border-orange">
				    <code class="mb0">
							<div>sortable('.o-sortable', {</div>
							<div class="px2">items: ':not(.disabled)'</div>
							<div>});</div>
						</code>
  				</div>
					<div class="mt2 bg-maroon border-top border-orange">
						<h4 id="eventName"></h4>
						<code><pre id="eventsConsole" style="overflow:auto"></pre></code>
					</div>
		    </div>
				<div class="col col-6">
					<ul class="ml4 js-sortable-disabled list flex flex-column list-reset">
						<li class="p1 mb1 maroon bg-orange">Item 1</li>
						<li class="p1 mb1 maroon bg-orange">Item 2</li>
						<li class="p1 mb1 maroon bg-orange">Item 3</li>
						<li class="disabled px1 mb1 maroon bg-orange muted">
							<div class="mb2 mt1">disabled 3</div>
							<ul class="list-reset m0 js-sortable-disabled-inner">
								<li class="p1 mb1 bg-maroon orange">Item 3.1</li>
								<li class="p1 mb1 bg-maroon orange">Item 3.2</li>
							</ul>
						</li>
						<li class="disabled p1 mb1 maroon bg-orange muted">disabled 5</li>
						<li class="p1 mb1 maroon bg-orange">Item 6</li>
					</ul>
					<script type="text/javascript">
						sortable('.js-sortable-disabled', {
							forcePlaceholderSize: true,
							items: ':not(.disabled)',
							placeholderClass: 'border border-orange mb1'
						});
						sortable('.js-sortable-disabled-inner', {
							forcePlaceholderSize: true,
							items: ':not(.disabled)',
							placeholderClass: 'border border-maroon mb1'
						});
						let eventTitle = document.querySelector('#eventName')
						let eventsConsole = document.querySelector('#eventsConsole')
						let sortableWithEvents = document.querySelector('.js-sortable-disabled')
						let events = ['sortstart','sortstop','sortupdate']
						events.forEach(function (eventName) {
							sortableWithEvents.addEventListener(eventName, function (e) {
								console.log('Fired: ', eventName)
								eventTitle.innerHTML = eventName
								eventsConsole.innerHTML = JSON.stringify(e.detail, null, ' ')
							})
						})
					</script>
		    </div>
			</div>

		</section>
		<section class="mb3 mx-auto col col-12">
  		<div class="p3 bg-white orange col col-6">
		    <h2 class="h3 m0">
					Connected lists
		    </h2>
				<p>Connected: This means an item can be dragged into another (connected) list.</p>
				<p class="mb2">Handles: Elements, e.g. || an item can be dragged with.</p>
				<ul class="js-sortable-connected list flex flex-column list-reset">
					<script>// scripts are needed for a test for indexes in sortupdate</script>
					<script></script>
					<script></script>
          <li class="p1 mb1 border border-white white bg-orange"><span class="js-handle px1">||</span><span draggable="true" ondragstart="console.log('I am testing that draggable elements do not act as handles')">Item 1</span></li>
					<li class="p1 mb1 border border-white white bg-orange">
						<div class="mb1"><span class="js-handle px1">||</span>Only 3 children allowed</div>
					<ul class="js-sortable-inner-connected list flex flex-column list-reset m0 py1">
						<li class="p1 mb1 border border-blue white bg-blue item"><span class="js-inner-handle px1">||</span>Inner item 1</li>
						<li class="p1 mb1 border border-blue white bg-blue item"><span class="js-inner-handle px1">||</span>Inner item 2</li>
					</ul>
					</li>
					<li class="p1 mb1 border border-white white bg-orange"><span class="js-handle px1">||</span>Item 3</li>
					<li class="p1 mb1 border border-white white bg-orange"><span class="js-handle px1">||</span>Item 4</li>
					<li class="p1 mb1 border border-white white bg-orange"><span class="js-handle px1">||</span>Item 5</li>
					<li class="p1 mb1 border border-white white bg-orange"><span class="js-handle px1">||</span>Item 6</li>
				</ul>
			</div>
			<div class="p3 bg-orange white col col-6">
				<div class="px3 py2 border border-white mb1">
					<code class="mb0">
						<div class="muted">// white & orange items</div>
						<div>sortable('.o-sortable', {</div>
						<div class="px2">connectWith: 'js-connected'</div>
						<div>});</div>
						<div class="muted">// blue items</div>
						<div>sortable('.o-sortable-inner', {</div>
						<div class="px2">connectWith: 'js-inner-connected'</div>
						<div>});</div>
					</code>
				</div>
				<ul class="js-sortable-connected list flex flex-column list-reset">
					<li class="p1 mb1 border border-orange orange bg-white"><span class="js-handle px1">||</span>Item 1</li>
					<li class="p1 mb1 border border-orange orange bg-white"><span class="js-handle px1">||</span>Item 2</li>
					<li class="p1 mb1 border border-orange orange bg-white"><span class="js-handle px1">||</span>Item 3</li>
					<li class="p1 mb1 border border-orange orange bg-white">
						<div class="mb1"><span class="js-handle px1">||</span>Only 3 children allowed</div>
						<ul class="js-sortable-inner-connected list flex flex-column list-reset mb0 py1">
							<li class="p1 mb1 border border-blue white bg-blue item"><span class="js-inner-handle px1">||</span>Inner item 3</li>
							<li class="p1 mb1 border border-blue white bg-blue item"><span class="js-inner-handle px1">||</span>Inner item 4</li>
						</ul>
					</li>
				</ul>
			</div>
		</section>
		<section class="mb3 mx-auto col col-12">
  		<div class="p3 clearfix bg-blue white">
				<div class="col col-6">
			    <h2 class="h3 m0">
						Exclude items & nested list
			    </h2>
					<div class="mt2 p2 bg-blue border border-white">
				    <code class="mb0">
							<div class="muted">// disabled / enable list</div>
							<div>sortable('.o-sortable', 'disable');</div>
							<div>sortable('.o-sortable', 'enable');</div>
							<div class="muted mt2">// reload list after adding items</div>
							<div>sortable('.o-sortable', 'reload');</div>
						</code>
  				</div>
		    </div>
				<div class="col col-6">
					<ul class="ml4 js-sortable-buttons list flex flex-column list-reset" data-disabled=false>
						<li class="p1 mb1 blue bg-white">Item 1</li>
						<li class="p1 mb1 blue bg-white">Item 2</li>
						<li class="p1 mb1 blue bg-white">Item 3</li>
						<li class="p1 mb1 blue bg-white">Item 4</li>
						<li class="p1 mb1 blue bg-white">Item 5</li>
						<li class="p1 mb1 blue bg-white">Item 6</li>
					</ul>
					<div class="center py2 ml4">
						<button class="js-disable button blue bg-white" data-text="Enable">Disable</button>
						<button class="js-add-item-button button blue bg-white">Add item</button>
						<button class="js-reload button button-outline white">Re-init</button>
					</div>
					<div class="center py1 ml4">
						<button class="js-destroy button blue bg-white">Destroy</button>
						<button class="js-init button blue bg-white">Init</button>
					</div>
		    </div>
			</div>
		</section>
    <section class="mb3 mx-auto col col-12">
      <div class="p3 clearfix bg-teal white">
          <div class="col col-4">
              <h2 class="h3 m0">
                  Sortable Table
              </h2>
              Tables rows can be sorted too, by making the container the
              <code class="yellow">tbody</code> and setting the <code class="yellow">items</code>
               property to <code class="yellow">tr</code>.
          </div>
          <div class="col col-6">
              <table class="ml4">
                  <thead class="bg-yellow">
                      <tr>
                          <td class="black">Food</td>
                          <td class="black">Topping</td>
                          <td class="black">Absolutely No</td>
                      </tr>
                  </thead>
                  <tbody class="js-sortable-table">
                      <tr><td></td></tr>
                      <tr class="border bg-white navy p4 js-sortable-tr">
                          <td>Taco</td>
                          <td>Salsa</td>
                          <td>Pickles</td>
                      </tr>
                      <tr class="border bg-white navy p4 js-sortable-tr">
                          <td>Burger</td>
                          <td>Lettuce</td>
                          <td>Rice</td>
                      </tr>
                      <tr class="border bg-white navy p4 js-sortable-tr">
                          <td>Pad Thai</td>
                          <td>Crushed Red Pepper</td>
                          <td>Spaghetti Noodles</td>
                      </tr>
                      <tr class="border bg-white navy p4 js-sortable-tr">
                          <td>Bratwurst</td>
                          <td>Sourkraut</td>
                          <td>Jelly</td>
                      </tr>
                  </tbody>
              </table>
              <script type="text/javascript">
                sortable('.js-sortable-table', {
                  items: "tr.js-sortable-tr",
                  placeholder: "<tr><td colspan=\"3\"><span class=\"center\">The row will appear here</span></td></tr>",
                  forcePlaceholderSize: false
                })
              </script>
              <table class="mt4 ml4 js-sortable-table-no-placeholder">
                <tbody>
                <tr class="border bg-white navy p4 js-sortable-tr"><td>Simple</td><td>Simple</td><td>Simple</td></tr>
                <tr class="border bg-white navy p4 js-sortable-tr"><td>Table</td><td>Table</td><td>Table</td></tr>
                <tr class="border bg-white navy p4 js-sortable-tr"><td>Bratwurst</td><td>Bratwurst</td><td>Bratwurst</td></tr>
                </tbody>
              </table>
              <script type="text/javascript">
              sortable('.js-sortable-table-no-placeholder tbody', {
                items: "tr",
                forcePlaceholderSize: true,
                placeholderClass: 'placeholder sort-placeholder',
              })
              </script>
          </div>
      </div>
    </section>

	<section class="mb3 mx-auto col col-12">
  		<div class="p3 clearfix bg-navy yellow">
				<div class="col col-6">
			    <h2 class="h3 m0">
						acceptFrom
			    </h2>
			     <p>acceptFrom allows to control which sortable to accept  drops from.</p>
			     <p>Item 1-6 are allows to be sorted with Item 7-12 but not the other way around.</p>
					<div class="mt2 p2 bg-navy border yellow border-yellow">
				    <code class="mb0">
						<div>sortable('.o-sortable1', {</div>
						<div>acceptFrom: false (accept from no one)</div>
						<div>});</div>
						<div>sortable('.o-sortable2', {</div>
						<div>acceptFrom: '.o-sortable1' (accept from .o-sortable1)</div>
						<div>});</div>
					</code>
  				</div>
		    </div>
			    <div class="col col-3">
						<ul class="ml4 js-sortable-oneway sortable list flex flex-column list-reset">
							<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 1</li>
							<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 2</li>
							<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 3</li>
							<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 4</li>
							<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 5</li>
							<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 6</li>
							<li class="mb1 bg-navy ghost border border-yellow" style="position: relative; z-index: 1; margin-top: -49px; height: 40px; display: block;">Ghost test</li>
						</ul>
			    </div>
				<div class="col col-3">
					<ul class="ml4 js-sortable-oneway-receive sortable list flex flex-column list-reset">
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 7</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 8</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 9</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 10</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 11</li>
						<li class="p1 mb1 navy bg-yellow" style="position: relative; z-index: 10">Item 12</li>
						<li class="mb1 bg-navy ghost border border-yellow" style="position: relative; z-index: 1; margin-top: -49px; height: 40px; display: block;">Ghost test</li>
					</ul>
		    </div>
			</div>
      <script>
      sortable('.js-sortable-oneway', {
          forcePlaceholderSize: true,
          acceptFrom: false,
          placeholderClass: 'mb1 bg-navy border border-yellow'
        });
        sortable('.js-sortable-oneway-receive', {
          forcePlaceholderSize: true,
          acceptFrom: '.js-sortable-oneway,.js-sortable-oneway-receive',
          placeholderClass: 'mb1 bg-navy border border-yellow',
          customDragImage: function (draggedElement, elementOffset, event) {
            draggedElement.style.border = "5px solid white"
            return{
              element: draggedElement,
              posX: event.pageX - elementOffset.left,
              posY: event.pageY - elementOffset.top
            }
          }
        });
      </script>
		</section>
		<section class="mb3 mx-auto col col-12">
  		<div class="p3 clearfix bg-yellow maroon">
			<div class="col col-12 mb1">
			<h2 class="h3 m0">Sortable Copy</h2>
			</div>
			<div class="col col-6">
				<div class="p2 bg-yellow border maroon border-maroon mt1">
				<code class="mb0">
					<div>sortable('.o-sortable', {</div>
					<div class="px2 muted">copy:true // default to false</div>
					<div class="px2 muted">maxItems: 2</div>
					<div>});</div>
				</code>
			</div>
				<h2 class="h4 mt1">Copy items here</h2>
				<ul class="p2 border maroon border-maroon js-sortable-copy-target sortable list flex flex-column list-reset">
				</ul>
		</div>
			<div class="col col-6">
				<ul class="ml4 js-sortable-copy sortable list flex flex-column list-reset">
					<li class="p1 mb1 yellow bg-maroon" style="position: relative; z-index: 10">Item 1</li>
					<li class="p1 mb1 yellow bg-maroon" style="position: relative; z-index: 10">Item 2</li>
					<li class="p1 mb1 yellow bg-maroon" style="position: relative; z-index: 10">Item 3</li>
					<li class="p1 mb1 yellow bg-maroon" style="position: relative; z-index: 10">Item 4</li>
					<li class="p1 mb1 yellow bg-maroon" style="position: relative; z-index: 10">Item 5</li>
					<li class="p1 mb1 yellow bg-maroon" style="position: relative; z-index: 10">Item 6</li>
				</ul>
			</div>
		</div>
		</section>
	</div>
	<script>
		sortable('.js-sortable-copy', {
		  forcePlaceholderSize: true,
		  copy: true,
				acceptFrom: false,
		  placeholderClass: 'mb1 bg-navy border border-yellow',
		});
		sortable('.js-sortable-copy-target', {
			forcePlaceholderSize: true,
			acceptFrom: '.js-sortable-copy,.js-sortable-copy-target',
			placeholderClass: 'mb1 border border-maroon',
			maxItems: 2
	  });
		sortable('.js-grid', {
					forcePlaceholderSize: true,
					placeholderClass: 'col col-4 border border-maroon'
				});
		sortable('.js-sortable-connected', {
			forcePlaceholderSize: true,
			connectWith: '.js-connected',
			handle: '.js-handle',
			items: 'li',
			placeholderClass: 'border border-white bg-orange mb1'
		});
		sortable('.js-sortable-inner-connected', {
			forcePlaceholderSize: true,
			connectWith: 'js-inner-connected',
			handle: '.js-inner-handle',
			items: '.item',
	maxItems: 3,
			placeholderClass: 'border border-white bg-orange mb1'
		});
		document.querySelector('.js-sortable-connected').addEventListener('sortupdate', function(e){
			console.log('Sortupdate: ', e.detail);
			console.log('Container: ', e.detail.origin.container, ' -> ', e.detail.destination.container);
			console.log('Index: '+e.detail.origin.index+' -> '+e.detail.destination.index);
			console.log('Element Index: '+e.detail.origin.elementIndex+' -> '+e.detail.destination.elementIndex);
		});

		document.querySelector('.js-sortable-connected').addEventListener('sortstart', function(e){
			console.log('Sortstart: ', e.detail);
		});

		document.querySelector('.js-sortable-connected').addEventListener('sortstop', function(e){
			console.log('Sortstop: ', e.detail);
		});

		sortable('.js-sortable-buttons', {
			forcePlaceholderSize: true,
			items: 'li',
			placeholderClass: 'border border-white mb1',
      hoverClass: 'bg-yellow'
		});
		// buttons to add items and reload the list
		// separately to showcase issue without reload
		document.querySelector('.js-add-item-button').addEventListener('click', function(){
			doc = new DOMParser().parseFromString(`<li class="p1 mb1 blue bg-white">new item</li>`, "text/html").body.firstChild;
			document.querySelector('.js-sortable-buttons').appendChild(doc);
		});

		document.querySelector('.js-reload').addEventListener('click', function(){
			console.log('Options before re-init:');
			console.log(document.querySelector('.js-sortable-buttons').h5s.data.opts);
			sortable('.js-sortable-buttons');
			console.log('Options after re-init:');
			console.log(document.querySelector('.js-sortable-buttons').h5s.data.opts);
		});
		// JS DISABLED
		document.querySelector('.js-disable').addEventListener('click', function(){
			var $list = document.querySelector('[data-disabled]');
			if ( $list.getAttribute('data-disabled') === 'false' ) {
				this.innerHTML = 'Enable';
				sortable($list, 'disable');
				$list.setAttribute('data-disabled', true);
				$list.classList.add('muted');
			} else {
				this.innerHTML = 'Disable';
				sortable($list, 'enable');
				$list.setAttribute('data-disabled', false);
				$list.classList.remove('muted');
			}
		});

		// Destroy & Init
		document.querySelector('.js-destroy').addEventListener('click', function(){
			sortable('.js-sortable-buttons', 'destroy');
		});
		document.querySelector('.js-init').addEventListener('click', function(){
			sortable('.js-sortable-buttons', {
				forcePlaceholderSize: true,
				items: 'li',
				placeholderClass: 'border border-white mb1'
			});
		});
	</script>
</body>
